package controller;

import java.io.*;
import java.lang.reflect.InvocationTargetException;

import dataStructure.LinkedList;
import dataStructure.ListNode;

import entity.Option;

public class ProgramFlowControl {
	private LinkedList<Option> options;
	private String optionGroupDescription;
	private Option teminateOption;

	public ProgramFlowControl(String str) {
		this.optionGroupDescription = str;
		options = new LinkedList<Option>();
	}

	public void addNewChoice(String letter, String description, Object obj, String mName) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
			IllegalAccessException, NoSuchMethodException, InvocationTargetException {
		// check whether the key is associated to any methods before.
		if (this.checkAvailable(letter)) {
			options.addNode(new ListNode<Option>(new Option(letter, description, obj, mName)));
		} else {
			System.out.println("System Warning: In ProgramFlowControl, choice with Key '" + letter + "' is defined before. " + mName + " is not added. ");
		}
	}

	// Before the program flow control class can be used,
	// user should define the corresponding key that will trigger different functions.
	private boolean checkAvailable(String val) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException,
			InvocationTargetException {
		// Check if it works
		Option result = options.searchContent("letter", val);
		if (result != null)
			return false;
		else
			return true;
	}

	// keep looping
	protected void flowControl() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException, InvocationTargetException,
			NoSuchMethodException {
		// List out all available choice of actions,
		// then launch a input stream for getting the option.
		// If no input is matched, return "NO_MATCH"
		// If 'x' is entered, the flow will be ended.

		// Show all options
		String c1;
		boolean isDone = false;

		if (this.teminateOption == null) {
			System.out.println("System error: In superclass ProgramFlowControl, teminateOption is not set.");
			isDone = true;
		}

		while (!isDone) {
			ListNode<Option> temp = this.options.getFirstNode();

			System.out.println(optionGroupDescription);
			while (temp != null) {
				System.out.println(temp.getContent().getValueByField("description"));
				temp = temp.getNext();
			}

			System.out.println(this.teminateOption.getValueByField("description"));
			
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			c1 = in.readLine();

			Option result = options.searchContent("letter", c1);
			if (result != null) {
				result.run();
			} else if (this.teminateOption.getLetter().equals(c1)) {
				this.teminateOption.run();
				isDone = true;
			}
		}
	}

	public Option getTeminateOption() {
		return teminateOption;
	}

	public void setTeminateOption(String letter, String description, Object obj, String mName) {
		this.teminateOption = new Option(letter, description, obj, mName);
	}
}
